home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / game / shoot / Orbit_src.lha / Orbit / source / hud.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-04  |  34.1 KB  |  1,506 lines

  1. /*
  2.     Amiga port by Oliver Gantert
  3.  
  4.     27.04.2000 - fixed some compiler warnings
  5.     21.06.2000 - changed glColor3d() to glColor3f()
  6.     04.07.2000 - fixed several missing glEnd() calls
  7.                  in MakeCircleList()
  8. */
  9. /*
  10.  
  11. ORBIT, a freeware space combat simulator
  12. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  13.  
  14. This program is free software; you can redistribute it and/or
  15. modify it under the terms of the GNU General Public License
  16. as published by the Free Software Foundation; either version 2
  17. of the License, or (at your option) any later version.
  18.  
  19. This program is distributed in the hope that it will be useful,
  20. but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22. GNU General Public License for more details.
  23.  
  24. You should have received a copy of the GNU General Public License
  25. along with this program; if not, write to the Free Software
  26. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  27.  
  28. */
  29.  
  30. #include "orbit.h"
  31.  
  32. static GLubyte throt_stipple[] = {
  33.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  34.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  35.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  36.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  37.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  38.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  39.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  40.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  41.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  42.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  43.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  44.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  45.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  46.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  47.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  48.   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
  49. }
  50. ;
  51.  
  52. void InitHud()
  53. /*
  54.  *  Initialize the HUD
  55.  */
  56. {
  57.   InitRadar();
  58.   MakeRadarCircleList();
  59.  
  60.   /* Figure out throttle coords */
  61.   hud.throt_min[0] = radar.fcenter[0] - 1.4*radar.fradius;
  62.   hud.throt_min[1] = radar.fcenter[1] - 0.9*radar.fradius;
  63.   hud.throt_max[0] = hud.throt_min[0] + 0.2*radar.fradius;
  64.   hud.throt_max[1] = hud.throt_min[1] + 1.8*radar.fradius;
  65.   hud.throt_mid[0] = hud.throt_min[0];
  66.   hud.throt_mid[1] = (hud.throt_min[1] + hud.throt_max[1]) * 0.5;
  67.  
  68.   /* Target name */
  69.   hud.targ_name[0] = radar.fcenter[0] + 2.0*radar.fradius;
  70.   hud.targ_name[1] = radar.fcenter[1] - radar.fradius + 10.0;
  71.  
  72.   /* Target range */
  73.   hud.targ_range[0] = hud.targ_name[0];
  74.   hud.targ_range[1] = hud.targ_name[1] - 10.0;
  75.  
  76.   /* Waypoint */
  77.   hud.waypoint[0] = hud.targ_range[0];
  78.   hud.waypoint[1] = hud.targ_range[1];
  79.  
  80.   /* Weapon name */
  81.   hud.weapon[0] = hud.targ_name[0];
  82.   hud.weapon[1] = radar.fcenter[1] + radar.fradius - 20.0;
  83.  
  84.   /* Velocity */
  85.   hud.vel[0] = radar.fcenter[0] - 3.0 * radar.fradius;
  86.   hud.vel[1] = hud.throt_mid[1] - 5.0;
  87.  
  88.   /* Shields display */
  89.   hud.shields_min[0] = radar.fcenter[0] + 1.2*radar.fradius;
  90.   hud.shields_max[0] = hud.shields_min[0] + 0.2*radar.fradius;
  91.   hud.shields_min[1] = hud.throt_min[1];
  92.   hud.shields_max[1] = hud.throt_max[1];
  93.  
  94.   /* Target shields */
  95.   hud.targshields_min[0] = radar.fcenter[0] + 1.5*radar.fradius;
  96.   hud.targshields_max[0] = hud.targshields_min[0] + 0.2*radar.fradius;
  97.   hud.targshields_min[1] = hud.throt_min[1];
  98.   hud.targshields_max[1] = hud.throt_max[1];
  99.  
  100.   lock.target = -1;
  101.   lock.type = LOCK_ENEMY;
  102. }
  103.  
  104. static GLubyte center_cursor[8] =
  105. {
  106.   0x10, 0x10, 0x00, 0xc6, 0x00, 0x10, 0x10, 0x00 }
  107. ;
  108.  
  109. void Hud()
  110. /*
  111.  *  Show the Heads Up Display
  112.  */
  113. {
  114.   char buf[256];
  115.  
  116.   /* Set up viewing matrix */
  117.   glMatrixMode (GL_MODELVIEW);
  118.   glPushMatrix();
  119.   glLoadIdentity();
  120.  
  121.   glMatrixMode (GL_PROJECTION);
  122.   glPushMatrix();
  123.   glLoadIdentity();
  124.  
  125.   glOrtho (0.0, ((double)ScreenWidth), 0.0, ((double)ScreenHeight), -1.0, 1.0);
  126.  
  127.   /* Disable three-D stuff */
  128.   glDisable (GL_DEPTH_TEST);
  129.   glDisable (GL_CULL_FACE);
  130.   glDisable (GL_LIGHTING);
  131.  
  132.   /* Try displaying a crosshair */
  133.   if (drawhud)
  134.   {
  135.     glColor3f (0.8, 0.8, 0.8);
  136.     glRasterPos2i (ScreenWidth/2, ScreenHeight/2);
  137.     glBitmap (8, 8, 3.0, 5.0, 0.0, 0.0, center_cursor);
  138.  
  139.     /* Display the radar */
  140.     Radar();
  141.  
  142.     /* Display the throttle */
  143.     Throttle();
  144.  
  145.     /* Velocity */
  146.     PlayerVel();
  147.  
  148.     /* Show target stuff */
  149.     TargetStuff();
  150.  
  151.     /* Current weapon */
  152.     ShowWeapon();
  153.  
  154.     /* Waypoint stuff */
  155.     WaypointStuff();
  156.  
  157.     /* Shields display */
  158.     Shields();
  159.  
  160.     /* Print the performance monitor */
  161.     if (showfps)
  162.     {
  163.       glColor3f (1.0, 1.0, 1.0);
  164.       glRasterPos2i (1, 5);
  165.  
  166.       sprintf (buf, "fps: %2.1f  ", fps);
  167.       Print (GLUT_BITMAP_HELVETICA_10, buf); 
  168.       
  169.       /* Show bandwidth */ 
  170.       if (am_client || am_server) 
  171.       {
  172.         if (recv_bps > 0.0) 
  173.         {
  174.           glColor3f (1.0, 0.0, 0.0); 
  175.           glRasterPos2i (1, 15); 
  176.           sprintf (buf, "R:%4.0lf  ", recv_bps); 
  177.           Print (GLUT_BITMAP_HELVETICA_10, buf); 
  178.         }
  179.         
  180.         if (xmit_bps > 0.0) 
  181.         {
  182.           glColor3f (0.0, 1.0, 0.0); 
  183.           glRasterPos2i (1, 25); 
  184.           sprintf (buf, "S:%4.0lf  ", xmit_bps); 
  185.           Print (GLUT_BITMAP_HELVETICA_10, buf); 
  186.         }
  187.       }
  188.     }
  189.   }
  190.  
  191.   /* Display the message console */
  192.   DisplayConsole();
  193.  
  194.   /* Display ceter-of-screen messages */
  195.   DrawMessage();
  196.  
  197.   glMatrixMode (GL_PROJECTION);
  198.   glPopMatrix();
  199.  
  200.   glMatrixMode (GL_MODELVIEW);
  201.   glPopMatrix();
  202.  
  203.   /* Draw various on-screen cursors */
  204.   if (drawhud)
  205.   {
  206.     /* The locked target */
  207.     DrawLock();
  208.  
  209.     /* Motion cursors */
  210.     DrawMotionCursors();
  211.  
  212.     /* Waypoint cursor */
  213.     DrawWaypoint();
  214.   }
  215.  
  216.   /* Re-enable three-D stuff */
  217.   glEnable (GL_DEPTH_TEST);
  218.   glEnable (GL_CULL_FACE);
  219.   glEnable (GL_LIGHTING);
  220. }
  221.  
  222. void RadarCoords (double *v, double *x, double *y)
  223. /*
  224.  *  Compute the two-D radar coordinates of an object
  225.  */
  226. {
  227.   double v2[3], v3[3], v4[3], t, r;
  228.  
  229.   /* Compute coords of object relative to player */
  230.   Vsub (v2, v, player.pos);
  231.  
  232.   /* Normalize that */
  233.   Normalize (v2);
  234.  
  235.   /* Distance of blip from center of radar is cosine of angle
  236.     between view direction and direction to object */
  237.   radarR = Dotp (player.view, v2);
  238.  
  239.   /* Find magnitude of projection of v2 onto view vector */
  240.   t = Dotp (v2, player.view);
  241.  
  242.   /* Determine projection of object on plane perpendicular
  243.     to viewing plane */
  244.   Vmul (v3, player.view, -t);
  245.   Vadd (v4, v3, v2);
  246.  
  247.   /* Handle special case of null v4, meaning object is on
  248.     line of sight */
  249.   if (0.0 == Mag2(v4))
  250.   {
  251.     radarCOS = 1.0;
  252.     radarSIN = 0.0;
  253.     return;
  254.   }
  255.  
  256.   /* Else normalize v4 */
  257.   Normalize (v4);
  258.  
  259.   /* v4 is now a vector from player's viewpoint to projection
  260.     of object on the player's plane.  Compute angle from player's
  261.     up vector to object */
  262.   radarCOS = Dotp (player.up, v4);
  263.   radarSIN = Dotp (player.right, v4);
  264.  
  265.   /* Convert to cartesian */
  266.   r = (1.0 - radarR) * 0.5;
  267.   *x = radar.fcenter[0] + radar.fradius * -r * radarSIN;
  268.   *y = radar.fcenter[1] + radar.fradius * r * radarCOS;
  269. }
  270.  
  271. void Radar()
  272. /*
  273.  *  Display the Wing Commander-like radar
  274.  */
  275. {
  276.   /* Draw the circle around the radar */
  277.   DrawRadarCircle();
  278.  
  279.   /* Draw the objects */
  280.   RadarPlanets();
  281.   RadarTargets();
  282.   RadarMissiles();
  283.   RadarWaypoint();
  284. }
  285.  
  286. void InitRadar()
  287. /*
  288.  *  Set up the radar coordinates
  289.  */
  290. {
  291.   radar.fcenter[0] = ScreenWidth * 0.5;
  292.   radar.center[0] = (int) radar.fcenter[0];
  293.  
  294.   radar.fcenter[1] = ScreenHeight * 0.125;
  295.   radar.center[1] = (int) radar.fcenter[1];
  296.  
  297.   radar.fradius = ScreenHeight * 0.125 - 10.0;
  298.   radar.radius = (int) radar.fradius;
  299. }
  300.  
  301. void DrawRadarCircle()
  302. {
  303.   glCallList (radar.list);
  304. }
  305.  
  306. void MakeRadarCircleList()
  307. /*
  308.  *  Define the radar circle list
  309.  */
  310. {
  311.   #if defined(AMIGA) && !defined(__PPC__)
  312.   float x, y, theta;
  313.   #else
  314.   double x, y, theta;
  315.   #endif
  316.  
  317.   /* Delete the list if it already exists */
  318.   if (glIsList (radar.list)) glDeleteLists (radar.list, 1);
  319.  
  320.   radar.list = glGenLists (1);
  321.   glNewList (radar.list, GL_COMPILE);
  322.  
  323.   glEnable (GL_POLYGON_STIPPLE);
  324.   glPolygonStipple (throt_stipple);
  325.  
  326.   /* Fill in radar circle */
  327.   glColor3f (0.0, 0.0, 0.1);
  328.   glBegin (GL_POLYGON);
  329.   for (theta=0.0; theta<6.29; theta+=0.314)
  330.   {
  331.     #if defined(AMIGA) && !defined(__PPC__)
  332.     y = (float) sin (theta);
  333.     x = (float) cos (theta);
  334.     x = (float)radar.fcenter[0] + x * (float)radar.fradius;
  335.     y = (float)radar.fcenter[1] + y * (float)radar.fradius;
  336.     glVertex2f (x, y);
  337.     #else
  338.     y = (double) sin ((double) theta);
  339.     x = (double) cos ((double) theta);
  340.     x = radar.fcenter[0] + x * radar.fradius;
  341.     y = radar.fcenter[1] + y * radar.fradius;
  342.     glVertex2d (x, y);
  343.     #endif
  344.   }
  345.   glEnd();
  346.  
  347.   /* Draw yellow border */
  348.   glColor3f (0.3, 0.3, 0.0);
  349.   glBegin (GL_LINE_LOOP);
  350.   for (theta=0.0; theta<6.29; theta+=0.314)
  351.   {
  352.     #if defined(AMIGA) && !defined(__PPC__)
  353.     y = (float) sin (theta);
  354.     x = (float) cos (theta);
  355.     x = (float)radar.fcenter[0] + x * (float)radar.fradius;
  356.     y = (float)radar.fcenter[1] + y * (float)radar.fradius;
  357.     glVertex2f (x, y);
  358.     #else
  359.     y = (double) sin ((double) theta);
  360.     x = (double) cos ((double) theta);
  361.     x = radar.fcenter[0] + x * radar.fradius;
  362.     y = radar.fcenter[1] + y * radar.fradius;
  363.     glVertex2d (x, y);
  364.     #endif
  365.   }
  366.   glEnd();
  367.  
  368.   /* Draw inner circle */
  369.   glBegin (GL_LINE_LOOP);
  370.   for (theta=0.0; theta<6.29; theta+=0.314)
  371.   {
  372.     #if defined(AMIGA) && !defined(__PPC__)
  373.     y = (float) sin (theta);
  374.     x = (float) cos (theta);
  375.     x = (float)radar.fcenter[0] + x * (float)radar.fradius * 0.5;
  376.     y = (float)radar.fcenter[1] + y * (float)radar.fradius * 0.5;
  377.     glVertex2f (x, y);
  378.     #else
  379.     y = (double) sin ((double) theta);
  380.     x = (double) cos ((double) theta);
  381.     x = radar.fcenter[0] + x * radar.fradius * 0.5;
  382.     y = radar.fcenter[1] + y * radar.fradius * 0.5;
  383.     glVertex2d (x, y);
  384.     #endif
  385.   }
  386.   glEnd();
  387.  
  388.   /* Draw connecting lines */
  389.   glBegin (GL_LINES);
  390.   #if defined(AMIGA) && !defined(__PPC__)
  391.   x = (float)radar.fcenter[0] + 0.7071 * (float)radar.fradius;
  392.   y = (float)radar.fcenter[1] + 0.7071 * (float)radar.fradius;
  393.   glVertex2f (x, y);
  394.   x = (float)radar.fcenter[0] + 0.7071 * (float)radar.fradius * 0.5;
  395.   y = (float)radar.fcenter[1] + 0.7071 * (float)radar.fradius * 0.5;
  396.   glVertex2f (x, y);
  397.   #else
  398.   x = radar.fcenter[0] + 0.7071 * radar.fradius;
  399.   y = radar.fcenter[1] + 0.7071 * radar.fradius;
  400.   glVertex2d (x, y);
  401.   x = radar.fcenter[0] + 0.7071 * radar.fradius * 0.5;
  402.   y = radar.fcenter[1] + 0.7071 * radar.fradius * 0.5;
  403.   glVertex2d (x, y);
  404.   #endif
  405.   glEnd();
  406.  
  407.   glBegin (GL_LINES);
  408.   #if defined(AMIGA) && !defined(__PPC__)
  409.   x = (float)radar.fcenter[0] - 0.7071 * (float)radar.fradius;
  410.   y = (float)radar.fcenter[1] + 0.7071 * (float)radar.fradius;
  411.   glVertex2f (x, y);
  412.   x = (float)radar.fcenter[0] - 0.7071 * (float)radar.fradius * 0.5;
  413.   y = (float)radar.fcenter[1] + 0.7071 * (float)radar.fradius * 0.5;
  414.   glVertex2f (x, y);
  415.   #else
  416.   x = radar.fcenter[0] - 0.7071 * radar.fradius;
  417.   y = radar.fcenter[1] + 0.7071 * radar.fradius;
  418.   glVertex2d (x, y);
  419.   x = radar.fcenter[0] - 0.7071 * radar.fradius * 0.5;
  420.   y = radar.fcenter[1] + 0.7071 * radar.fradius * 0.5;
  421.   glVertex2d (x, y);
  422.   #endif
  423.   glEnd();
  424.  
  425.   glBegin (GL_LINES);
  426.   #if defined(AMIGA) && !defined(__PPC__)
  427.   x = (float)radar.fcenter[0] - 0.7071 * (float)radar.fradius;
  428.   y = (float)radar.fcenter[1] - 0.7071 * (float)radar.fradius;
  429.   glVertex2f (x, y);
  430.   x = (float)radar.fcenter[0] - 0.7071 * (float)radar.fradius * 0.5;
  431.   y = (float)radar.fcenter[1] - 0.7071 * (float)radar.fradius * 0.5;
  432.   glVertex2f (x, y);
  433.   #else
  434.   x = radar.fcenter[0] - 0.7071 * radar.fradius;
  435.   y = radar.fcenter[1] - 0.7071 * radar.fradius;
  436.   glVertex2d (x, y);
  437.   x = radar.fcenter[0] - 0.7071 * radar.fradius * 0.5;
  438.   y = radar.fcenter[1] - 0.7071 * radar.fradius * 0.5;
  439.   glVertex2d (x, y);
  440.   #endif
  441.   glEnd();
  442.  
  443.   glBegin (GL_LINES);
  444.   #if defined(AMIGA) && !defined(__PPC__)
  445.   x = radar.fcenter[0] + 0.7071 * radar.fradius;
  446.   y = radar.fcenter[1] - 0.7071 * radar.fradius;
  447.   glVertex2f (x, y);
  448.   x = radar.fcenter[0] + 0.7071 * radar.fradius * 0.5;
  449.   y = radar.fcenter[1] - 0.7071 * radar.fradius * 0.5;
  450.   glVertex2f (x, y);
  451.   #else
  452.   x = radar.fcenter[0] + 0.7071 * radar.fradius;
  453.   y = radar.fcenter[1] - 0.7071 * radar.fradius;
  454.   glVertex2d (x, y);
  455.   x = radar.fcenter[0] + 0.7071 * radar.fradius * 0.5;
  456.   y = radar.fcenter[1] - 0.7071 * radar.fradius * 0.5;
  457.   glVertex2d (x, y);
  458.   #endif
  459.   glEnd();
  460.  
  461.   glDisable (GL_POLYGON_STIPPLE);
  462.  
  463.   glEndList();
  464. }
  465.  
  466. void RadarPlanets()
  467. /*
  468.  *  Draw the planets on the radar
  469.  */
  470. {
  471.   int p;
  472.   double x, y;
  473.  
  474.   for (p=0; p<NPLANETS; p++)
  475.   {
  476.     if (!planet[p].hidden)
  477.     {
  478.       if ((!planet[p].is_moon) || (planet[p].range2 < (1000.0 * 1000.0)))
  479.       {
  480.         /* Convert to radar coords */
  481.         RadarCoords (planet[p].pos, &x, &y);
  482.  
  483.         /* Draw it */
  484.         if ( (lock.type == LOCK_PLANET) &&
  485.         (lock.target == p) )
  486.         {
  487.           glPointSize (4.0);
  488.         }
  489.         else
  490.         {
  491.           glPointSize (3.0);
  492.         }
  493.         glBegin (GL_POINTS);
  494.         if (planet[p].is_moon)
  495.         glColor3f (0.0, 1.0, 1.0);
  496.         else
  497.         glColor3f (0.0, 0.0, 1.0);
  498.         glVertex2d (x, y);
  499.         glEnd();
  500.       }
  501.     }
  502.   }
  503. }
  504.  
  505. void RadarTargets()
  506. /*
  507.  *  Draw the targets on the radar
  508.  */
  509. {
  510.   double x, y;
  511.   int i;
  512.  
  513.   /* glColor3f (0.9, 0.0, 0.0); */
  514.  
  515.   for (i=0; i<NTARGETS; i++)
  516.   {
  517.     /* Is this a network game and this target is us? */
  518.     /*  if (am_client && (i == client[clientme.client].target)) continue; */
  519.     if (am_server && (i == client[server.client].target)) continue;
  520.  
  521.     if ( (target[i].age > 0.0) &&
  522.     (target[i].range2 < TARG_MAXRANGE2) &&
  523.     (!target[i].hidden) &&
  524.     (!target[i].invisible) )
  525.     {
  526.       /* Convert to radar coords */
  527.       RadarCoords (target[i].pos, &x, &y);
  528.  
  529.       /* Select color */
  530.       if (target[i].friendly)
  531.       glColor3f (0.0, 0.9, 0.0);
  532.       else
  533.       glColor3f (0.9, 0.0, 0.0);
  534.  
  535.       /* Draw locked target bigger */
  536.       if (i == lock.target)
  537.       {
  538.         glPointSize (3.0);
  539.         glBegin (GL_POINTS);
  540.         glVertex2d (x, y);
  541.       }
  542.       else
  543.       {
  544.         /* Just Draw it */
  545.         glPointSize (2.0);
  546.         glBegin (GL_POINTS);
  547.         glVertex2d (x, y);
  548.       }
  549.  
  550.       glEnd();
  551.     }
  552.   }
  553.   glEnd();
  554. }
  555.  
  556. void RadarMissiles()
  557. /*
  558.  *  Draw the missiles on the radar
  559.  */
  560. {
  561.   double x, y;
  562.   int i;
  563.  
  564.   glPointSize (1.0);
  565.   glBegin (GL_POINTS);
  566.  
  567.   /* Missiles are yellow */
  568.   glColor3f (1.0, 1.0, 0.0);
  569.  
  570.   for (i=0; i<NMSLS; i++)
  571.   {
  572.     if (msl[i].age > 0.0)
  573.     {
  574.       /* Convert to radar coords */
  575.       RadarCoords (msl[i].pos, &x, &y);
  576.  
  577.       /* Draw it */
  578.       glVertex2d (x, y);
  579.     }
  580.   }
  581.   glEnd();
  582. }
  583.  
  584. void RadarWaypoint()
  585. /*
  586.  *  Draw the current waypoint
  587.  */
  588. {
  589.   double x, y;
  590.   int w;
  591.  
  592.   if ((-1) == (w = player.waypoint)) return;
  593.  
  594.   glPointSize (2.0);
  595.   glBegin (GL_POINTS);
  596.   glColor3f (1.0, 1.0, 1.0);
  597.   RadarCoords (waypoint[w].pos, &x, &y);
  598.   glVertex2d (x, y);
  599.   glEnd();
  600. }
  601.  
  602. void LockNearest()
  603. /*
  604.  *  Lock onto the nearest target
  605.  */
  606. {
  607.   int t, ok;
  608.   double d;
  609.  
  610.   d = -1.0;
  611.  
  612.   if (lock.type == LOCK_ENEMY)
  613.   {
  614.     for (t=0; t<NTARGETS; t++)
  615.     {
  616.       if (am_client || am_server) 
  617.       {
  618.         /* Can lock distant targets in network games */ 
  619.         ok = ( (target[t].age > 0.0) && 
  620.         (!target[t].hidden) && 
  621.         (!target[t].invisible) && 
  622.         (!target[t].friendly) ); 
  623.       }
  624.       else 
  625.       {
  626.         ok = ( (target[t].age > 0.0) && 
  627.         (!target[t].hidden) && 
  628.         (!target[t].invisible) && 
  629.         (!target[t].friendly) && 
  630.         (target[t].range2 < TARG_MAXRANGE2) ); 
  631.       }
  632.       
  633.       if (ok)
  634.       {
  635.         if ( (d < 0.0) || (target[t].range2 < d) )
  636.         {
  637.           d = target[t].range2;
  638.           lock.target = t;
  639.         }
  640.       }
  641.     }
  642.   }
  643.   else if (lock.type == LOCK_FRIENDLY)
  644.   {
  645.     for (t=0; t<NTARGETS; t++)
  646.     {
  647.       if ( (target[t].age > 0.0) &&
  648.       (!target[t].hidden) &&
  649.       (!target[t].invisible) &&
  650.       (target[t].range2 < TARG_MAXRANGE2) &&
  651.       (target[t].friendly) )
  652.       {
  653.         if ( (d < 0.0) || (target[t].range2 < d) )
  654.         {
  655.           d = target[t].range2;
  656.           lock.target = t;
  657.         }
  658.       }
  659.     }
  660.   }
  661.   else if (lock.type == LOCK_PLANET)
  662.   {
  663.     for (t=0; t<NPLANETS; t++)
  664.     {
  665.       if (!planet[t].hidden)
  666.       {
  667.         if ( (d < 0.0) || (planet[t].absrange2 < d) )
  668.         {
  669.           d = planet[t].absrange2;
  670.           lock.target = t;
  671.         }
  672.       }
  673.     }
  674.   }
  675. }
  676.  
  677. void LockNext()
  678. /*
  679.  *  Lock onto next target
  680.  */
  681. {
  682.   int t, tt, old, ok;
  683.  
  684.   old = lock.target;
  685.  
  686.   /* Check if we're not locked yet */
  687.   if (lock.target == -1) lock.target = 0;
  688.  
  689.   if (lock.type == LOCK_ENEMY)
  690.   {
  691.     for (t=lock.target; t<lock.target+NTARGETS; t++)
  692.     {
  693.       tt = t % NTARGETS;
  694.       
  695.       if (am_client || am_server) 
  696.       {
  697.         /* Can lock distant targets in network games */ 
  698.         ok = ( (target[tt].age > 0.0) && 
  699.         (!target[tt].hidden) && 
  700.         (!target[tt].invisible) && 
  701.         (!target[tt].friendly) && 
  702.         (tt != old) ); 
  703.       }
  704.       else 
  705.       {
  706.         ok = ( (target[tt].age > 0.0) &&
  707.         (!target[tt].hidden) &&
  708.         (!target[tt].invisible) &&
  709.         (!target[tt].friendly) &&
  710.         (target[tt].range2 < TARG_MAXRANGE2) &&
  711.         (tt != old) ); 
  712.       }
  713.       
  714.       if (ok)
  715.       {
  716.         lock.target = tt;
  717.         return;
  718.       }
  719.     }
  720.   }
  721.   else if (lock.type == LOCK_FRIENDLY)
  722.   {
  723.     for (t=lock.target; t<lock.target+NTARGETS; t++)
  724.     {
  725.       tt = t % NTARGETS;
  726.  
  727.       if ( (target[tt].age > 0.0) &&
  728.       (!target[tt].hidden) &&
  729.       (!target[tt].invisible) &&
  730.       (target[tt].friendly) &&
  731.       (target[tt].range2 < TARG_MAXRANGE2) &&
  732.       (tt != old) )
  733.       {
  734.         lock.target = tt;
  735.         return;
  736.       }
  737.     }
  738.   }
  739.   else if (lock.type == LOCK_PLANET)
  740.   {
  741.     do
  742.     {
  743.       lock.target = (lock.target + 1) % NPLANETS;
  744.     }
  745.     while ( (planet[lock.target].is_moon &&
  746.     (planet[lock.target].range2 > (5000.0*5000.0)) ) ||
  747.     planet[lock.target].hidden);
  748.     return;
  749.   }
  750.  
  751.   /* Nothing new to lock onto */
  752.   lock.target = old;
  753. }
  754.  
  755. void LockPrev()
  756. /*
  757.  *  Lock onto previous target
  758.  */
  759. {
  760.   int t, tt, old, ok;
  761.  
  762.   old = lock.target;
  763.  
  764.   /* Check if we're not locked yet */
  765.   if (lock.target == -1) lock.target = 0;
  766.  
  767.   if (lock.type == LOCK_ENEMY)
  768.   {
  769.     for (t=lock.target+NTARGETS; t>lock.target; t--)
  770.     {
  771.       tt = t % NTARGETS;
  772.       
  773.       if (am_client || am_server) 
  774.       {
  775.         ok = ( (target[tt].age > 0.0) && 
  776.         (!target[tt].hidden) && 
  777.         (!target[tt].invisible) && 
  778.         (!target[tt].friendly) && 
  779.         (tt != old) ); 
  780.       }
  781.       else 
  782.       {
  783.         ok = ( (target[tt].age > 0.0) && 
  784.         (!target[tt].hidden) && 
  785.         (!target[tt].invisible) && 
  786.         (!target[tt].friendly) && 
  787.         (target[tt].range2 < TARG_MAXRANGE2) && 
  788.         (tt != old) ); 
  789.       }
  790.       
  791.       if (ok) 
  792.       {
  793.         lock.target = tt;
  794.         return;
  795.       }
  796.     }
  797.   }
  798.   else if (lock.type == LOCK_FRIENDLY)
  799.   {
  800.     for (t=lock.target+NTARGETS; t>lock.target; t--)
  801.     {
  802.       tt = t % NTARGETS;
  803.  
  804.       if ( (target[tt].age > 0.0) &&
  805.       (!target[tt].hidden) &&
  806.       (!target[tt].invisible) &&
  807.       (target[tt].friendly) &&
  808.       (target[tt].range2 < TARG_MAXRANGE2) &&
  809.       (tt != old) )
  810.       {
  811.         lock.target = tt;
  812.         return;
  813.       }
  814.     }
  815.   }
  816.   else if (lock.type == LOCK_PLANET)
  817.   {
  818.     do
  819.     {
  820.       lock.target = (lock.target + NPLANETS - 1) % NPLANETS;
  821.     }
  822.     while ( (planet[lock.target].is_moon &&
  823.     (planet[lock.target].range2 > (5000.0*5000.0)) ) ||
  824.     planet[lock.target].hidden);
  825.     return;
  826.   }
  827.  
  828.   /* Nothing new to lock onto */
  829.   lock.target = old;
  830. }
  831.  
  832. void CheckLock()
  833. /*
  834.  *  Sanity checks on the locked target
  835.  */
  836. {
  837.   int l;
  838.  
  839.   l = lock.target;
  840.  
  841.   if (lock.type == LOCK_PLANET)
  842.   {
  843.     /* Can't lock hidden planets */
  844.     if (planet[l].hidden) lock.target = -1;
  845.   }
  846.  
  847.   if (lock.type == LOCK_FRIENDLY)
  848.   {
  849.     if (!target[l].friendly) lock.type = LOCK_ENEMY;
  850.     if (target[l].hidden) lock.target = -1;
  851.     if (target[l].invisible) lock.target = -1;
  852.     if (target[l].age == 0.0) lock.target = -1;
  853.     if (target[l].range2 > TARG_MAXRANGE2) lock.target = -1;
  854.   }
  855.  
  856.   if (lock.type == LOCK_ENEMY)
  857.   {
  858.     if (target[l].friendly) lock.type = LOCK_FRIENDLY;
  859.     if (target[l].hidden) lock.target = -1;
  860.     if (target[l].invisible) lock.target = -1;
  861.     if (target[l].age == 0.0) lock.target = -1; 
  862.     
  863.     if (!am_client && !am_server) 
  864.     {
  865.       if (target[l].range2 > TARG_MAXRANGE2) lock.target = -1; 
  866.     }
  867.   }
  868. }
  869.  
  870. static GLubyte lock_cursor[32] =
  871. {
  872.   0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
  873.   0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
  874.   0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
  875.   0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff }
  876. ;
  877.  
  878. static GLubyte aim_cursor[8] =
  879. {
  880.   0x81, 0x42, 0x24, 0x00, 0x00, 0x24, 0x42, 0x81 }
  881. ;
  882.  
  883. static GLubyte motion_cursor[8] =
  884. {
  885.   0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18 }
  886. ;
  887.  
  888. static GLubyte waypoint_cursor[8] =
  889. {
  890.   0x3c, 0x00, 0x81, 0x81, 0x81, 0x81, 0x00, 0x3c }
  891. ;
  892.  
  893. void DrawLock()
  894. /*
  895.  *  Draw the lock cursor
  896.  */
  897. {
  898.   char v;
  899.   double vtarg[3], v1[3];
  900.  
  901.   /* Don't bother if we're not locked */
  902.   if (lock.target == -1) return;
  903.  
  904.   /* Planets are special */
  905.   if (lock.type == LOCK_PLANET)
  906.   {
  907.     DrawPlanetLock();
  908.     return;
  909.   }
  910.  
  911.   /* Or if out of range */ 
  912.   if (!am_client && !am_server) 
  913.   {
  914.     if (target[lock.target].range2 > TARG_MAXRANGE2) return; 
  915.   }
  916.  
  917.   /* Select color */
  918.   if (target[lock.target].friendly)
  919.   glColor3f (0.0, 0.9, 0.0);
  920.   else
  921.   glColor3f (0.9, 0.0, 0.0);
  922.  
  923.   /* Set raster position, check if valid */
  924.   Vsub (v1, target[lock.target].pos, player.pos);
  925.   glRasterPos3dv (v1);
  926.   glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  927.   if (v)
  928.   {
  929.     /* Draw cursor */
  930.     glBitmap (16, 16, 8.0, 8.0, 0.0, 0.0, lock_cursor);
  931.   }
  932.  
  933.   /* Try to draw the aiming cursor */
  934.   if (target[lock.target].range2 > weapon[player.weapon].range2) return; 
  935.   if (!target[lock.target].friendly)
  936.   {
  937.     if (!am_client && !am_server) 
  938.     {
  939.       Vmul (v1, player.up, -0.01);
  940.       Vadd (v1, v1, player.pos); 
  941.     }
  942.     else 
  943.     {
  944.       Vset (v1, player.pos); 
  945.     }
  946.     if (Aim (vtarg, v1, player.vel,
  947.     target[lock.target].pos, target[lock.target].vel,
  948.     weapon[player.weapon].speed) )
  949.     {
  950.       glColor3f (1.0, 1.0, 0.0);
  951.       Vsub (vtarg, vtarg, player.pos);
  952.       glRasterPos3dv (vtarg);
  953.       glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  954.       if (v)
  955.       {
  956.         glBitmap (8, 8, 4.0, 4.0, 0.0, 0.0, aim_cursor);
  957.       }
  958.     }
  959.   }
  960. }
  961.  
  962. void DrawPlanetLock()
  963. {
  964.   int p;
  965.   char v;
  966.   double v1[3];
  967.  
  968.   p = lock.target;
  969.  
  970.   if (planet[p].is_moon)
  971.   glColor3f (0.0, 1.0, 1.0);
  972.   else
  973.   glColor3f (0.0, 0.0, 1.0);
  974.  
  975.   /* Set raster postition, check if valid */
  976.   Vsub (v1, planet[p].pos, player.pos);
  977.   glRasterPos3dv (v1);
  978.   glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  979.   if (v)
  980.   {
  981.     /* Draw cursor */
  982.     glBitmap (16, 16, 8.0, 8.0, 0.0, 0.0, lock_cursor);
  983.   }
  984. }
  985.  
  986. void DrawWaypoint()
  987. {
  988.   int w;
  989.   char v;
  990.   double v1[3];
  991.  
  992.   w = player.waypoint;
  993.   if (w == (-1)) return;
  994.  
  995.   glColor3f (0.8, 0.8, 1.8);
  996.  
  997.   /* Set raster postition, check if valid */
  998.   Vsub (v1, waypoint[w].pos, player.pos);
  999.   glRasterPos3dv (v1);
  1000.   glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  1001.   if (v)
  1002.   {
  1003.     /* Draw cursor */
  1004.     glBitmap (8, 8, 3.0, 4.0, 0.0, 0.0, waypoint_cursor);
  1005.   }
  1006. }
  1007.  
  1008. void DrawMotionCursors()
  1009. /*
  1010.  *  Show forward and reverse motion
  1011.  */
  1012. {
  1013.   double vn[3];
  1014.   char v;
  1015.  
  1016.   /* Not in arcade mode */
  1017.   if (player.flightmodel == FLIGHT_ARCADE) return;
  1018.  
  1019.   /* Not unless we're moving */
  1020.   if ( (0.0 == player.vel[0]) &&
  1021.   (0.0 == player.vel[1]) &&
  1022.   (0.0 == player.vel[2]) ) return;
  1023.  
  1024.   /* Forward cursor */
  1025.   Vset (vn, player.vel);
  1026.   Normalize (vn);
  1027.  
  1028.   glColor3f (0.0, 0.8, 0.0);
  1029.   glRasterPos3dv (vn);
  1030.   glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  1031.   if (v)
  1032.   {
  1033.     /* Draw cursor */
  1034.     glBitmap (8, 8, 4.0, 4.0, 0.0, 0.0, motion_cursor);
  1035.   }
  1036.  
  1037.   /* Reverse cursor */
  1038.   Vmul (vn, vn, -1.0);
  1039.   
  1040.   glColor3f (0.8, 0.0, 0.0);
  1041.   glRasterPos3dv (vn);
  1042.   glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  1043.   if (v)
  1044.   {
  1045.     /* Draw cursor */
  1046.     glBitmap (8, 8, 4.0, 4.0, 0.0, 0.0, motion_cursor);
  1047.   }
  1048. }
  1049.  
  1050. int Aim (double *vtarg, double *pos0, double *vel0, double *pos1, double *vel1, double vel)
  1051. /*
  1052.  *  Something at position pos0, with velocity vector vel0,
  1053.  *  wants to shoot a missile with velocity "vel" at a target
  1054.  *  at position pos1, moving with vector vel1.
  1055.  *
  1056.  *  Coord of place to shoot will be in vtarg, unless there is
  1057.  *  no solution, in which case we return FALSE.
  1058.  */
  1059. {
  1060.   double va[3], vb[3], A, B, C, D, t, t1, t2, rootD;
  1061.  
  1062.   /* va is position of target wrt shooter */
  1063.   Vsub (va, pos1, pos0);
  1064.  
  1065.   /* vb is relative velocity of target */
  1066.   Vsub (vb, vel1, vel0);
  1067.  
  1068.   /* If there's a solution, then there exists some t such
  1069.     that target postion (va) plus t times its velocity (vb)
  1070.     is as far away from shooter (origin) as a missile can
  1071.     travel in time t (t*vel).  If you work it out you get
  1072.     a pretty simple quadratic equation. */
  1073.  
  1074.   /* Set up coefficients of quadratic equation */
  1075.   A = vb[0]*vb[0] + vb[1]*vb[1] + vb[2]*vb[2] - vel*vel;
  1076.   B = 2.0*va[0]*vb[0] + 2.0*va[1]*vb[1] + 2.0*va[2]*vb[2];
  1077.   C = va[0]*va[0] + va[1]*va[1] + va[2]*va[2];
  1078.  
  1079.   /* This is the kind of stuff you thought you'd never
  1080.     use in real life, isn't it? */
  1081.  
  1082.   /* A == 0 is special case */
  1083.   if (A == 0.0)
  1084.   {
  1085.     /* A==0 && B==0 implies no solution */
  1086.     if (B == 0.0) return (0);
  1087.  
  1088.     /* Simple solution */
  1089.     t = (-C / B);
  1090.  
  1091.     /* Can't shoot missiles backwards */
  1092.     if (t < 0.0) return (0);
  1093.   }
  1094.   else
  1095.   {
  1096.     /* More complicated cases */
  1097.     /* Compute discriminant */
  1098.     D = B*B - 4.0*A*C;
  1099.  
  1100.     /* D < 0 implies no solution */
  1101.     if (D < 0.0) return (0);
  1102.  
  1103.     /* D == 0 implies one solution */
  1104.     if (D == 0.0)
  1105.     {
  1106.       t = -B / (2.0 * A);
  1107.       if (t <= 0.0) return (0);
  1108.     }
  1109.     else
  1110.     {
  1111.       /* Two solutions */
  1112.       rootD = sqrt (D);
  1113.       t1 = (-B + rootD) / (2.0 * A);
  1114.       t2 = (-B - rootD) / (2.0 * A);
  1115.  
  1116.       /* We need a non-negative solution */
  1117.       if ( (t1 < 0.0) && (t2 < 0.0) ) return (0);
  1118.  
  1119.       if (t1 < 0.0)
  1120.       t = t2;
  1121.       else if (t2 < 0.0)
  1122.       t = t1;
  1123.       else
  1124.       {
  1125.         /* Both non-negative, choose lesser
  1126.        (closer to target) */
  1127.         if (t1 < t2)
  1128.         t = t1;
  1129.         else
  1130.         t = t2;
  1131.       }
  1132.     }
  1133.   }
  1134.  
  1135.   /* Whew!  We have a solution in t now. */
  1136.   Vmul (vtarg, vb, t);
  1137.   Vadd (vtarg, vtarg, va);
  1138.   Vadd (vtarg, vtarg, pos0);
  1139.  
  1140.   return (1);
  1141. }
  1142.  
  1143. void ArcadeThrottle()
  1144. /*
  1145.  *  Draw the throttle for arcade mode
  1146.  */
  1147. {
  1148.   double y;
  1149.  
  1150.   glEnable (GL_POLYGON_STIPPLE);
  1151.   glPolygonStipple (throt_stipple);
  1152.  
  1153.   /* First draw unshaded background */
  1154.   glColor3f (0.0, 0.25, 0.0);
  1155.   glBegin (GL_QUAD_STRIP);
  1156.   glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1157.   glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1158.   glVertex2d (hud.throt_min[0], hud.throt_max[1]);
  1159.   glVertex2d (hud.throt_max[0], hud.throt_max[1]);
  1160.   glEnd();
  1161.  
  1162.   if (player.throttle > MAX_THROTTLE)
  1163.   {
  1164.     y = hud.throt_min[1] + (player.throttle / MAX_WARP_THROTTLE) *
  1165.     (hud.throt_max[1] - hud.throt_min[1]);
  1166.   }
  1167.   else
  1168.   {
  1169.     y = hud.throt_min[1] + (player.throttle / MAX_THROTTLE) *
  1170.     (hud.throt_max[1] - hud.throt_min[1]);
  1171.   }
  1172.  
  1173.   glColor3f (0.0, 0.75, 0.0);
  1174.   glBegin (GL_QUAD_STRIP);
  1175.   glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1176.   glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1177.   glVertex2d (hud.throt_min[0], y);
  1178.   glVertex2d (hud.throt_max[0], y);
  1179.   glEnd();
  1180.  
  1181.   glDisable (GL_POLYGON_STIPPLE);
  1182.  
  1183.   /* If travelling at warp speed, put a border around throttle */
  1184.   if (player.throttle > MAX_THROTTLE)
  1185.   {
  1186.     glColor3f (0.5, 0.5, 0.0);
  1187.     glBegin (GL_LINE_LOOP);
  1188.     glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1189.     glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1190.     glVertex2d (hud.throt_max[0], hud.throt_max[1]);
  1191.     glVertex2d (hud.throt_min[0], hud.throt_max[1]);
  1192.     glEnd();
  1193.   }
  1194. }
  1195.  
  1196. void Throttle()
  1197. /*
  1198.  *  Draw the throttle
  1199.  */
  1200. {
  1201.   double y;
  1202.  
  1203.   /* Arcade mode is special */
  1204.   if (player.flightmodel == FLIGHT_ARCADE)
  1205.   {
  1206.     ArcadeThrottle();
  1207.     return;
  1208.   }
  1209.   
  1210.   glEnable (GL_POLYGON_STIPPLE);
  1211.   glPolygonStipple (throt_stipple);
  1212.  
  1213.   /* First draw unshaded background */
  1214.   glColor3f (0.25, 0.0, 0.0);
  1215.   glBegin (GL_QUAD_STRIP);
  1216.   glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1217.   glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1218.   glVertex2d (hud.throt_min[0], hud.throt_mid[1]);
  1219.   glVertex2d (hud.throt_max[0], hud.throt_mid[1]);
  1220.   glEnd();
  1221.   glColor3f (0.0, 0.25, 0.0);
  1222.   glBegin (GL_QUAD_STRIP);
  1223.   glVertex2d (hud.throt_min[0], hud.throt_mid[1]);
  1224.   glVertex2d (hud.throt_max[0], hud.throt_mid[1]);
  1225.   glVertex2d (hud.throt_min[0], hud.throt_max[1]);
  1226.   glVertex2d (hud.throt_max[0], hud.throt_max[1]);
  1227.   glEnd();
  1228.  
  1229.   /* Now show the throttle */
  1230.   if (player.move_forward > 0.0)
  1231.   {
  1232.     glColor3f (0.0, 0.75, 0.0);
  1233.     y = hud.throt_mid[1] + player.move_forward *
  1234.     (hud.throt_max[1] - hud.throt_mid[1]);
  1235.     glBegin (GL_QUAD_STRIP);
  1236.     glVertex2d (hud.throt_min[0], hud.throt_mid[1]);
  1237.     glVertex2d (hud.throt_max[0], hud.throt_mid[1]);
  1238.     glVertex2d (hud.throt_min[0], y);
  1239.     glVertex2d (hud.throt_max[0], y);
  1240.     glEnd();
  1241.   }
  1242.   else if (player.move_backward > 0.0)
  1243.   {
  1244.     glColor3f (0.75, 0.0, 0.0);
  1245.     y = hud.throt_mid[1] - player.move_backward *
  1246.     (hud.throt_mid[1] - hud.throt_min[1]);
  1247.     glBegin (GL_QUAD_STRIP);
  1248.     glVertex2d (hud.throt_min[0], hud.throt_mid[1]);
  1249.     glVertex2d (hud.throt_max[0], hud.throt_mid[1]);
  1250.     glVertex2d (hud.throt_min[0], y);
  1251.     glVertex2d (hud.throt_max[0], y);
  1252.     glEnd();
  1253.   }
  1254.  
  1255.   glDisable (GL_POLYGON_STIPPLE);
  1256.  
  1257.   /* If travelling at warp speed, put a border around throttle */
  1258.   if (warpspeed)
  1259.   {
  1260.     glColor3f (0.5, 0.5, 0.0);
  1261.     glBegin (GL_LINE_LOOP);
  1262.     glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1263.     glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1264.     glVertex2d (hud.throt_max[0], hud.throt_max[1]);
  1265.     glVertex2d (hud.throt_min[0], hud.throt_max[1]);
  1266.     glEnd();
  1267.   }
  1268. }
  1269.  
  1270. void TargetStuff()
  1271. /*
  1272.  *  Show stuff about the locked target
  1273.  */
  1274. {
  1275.   int t;
  1276.   double r;
  1277.   char buf[32];
  1278.  
  1279.   /* Planet lock is special */
  1280.   if (lock.type == LOCK_PLANET)
  1281.   {
  1282.     PlanetStuff();
  1283.     return;
  1284.   }
  1285.  
  1286.   if (-1 != (t = lock.target))
  1287.   {
  1288.     /* Bail if too far away */ 
  1289.     if (!am_client && !am_server) 
  1290.     {
  1291.       if (target[lock.target].range2 > TARG_MAXRANGE2) return; 
  1292.     }
  1293.  
  1294.     /* Target name */
  1295.     if (target[t].friendly)
  1296.     glColor3f (0.0, 0.8, 0.0);
  1297.     else
  1298.     glColor3f (0.8, 0.0, 0.0);
  1299.  
  1300.     glRasterPos2dv (hud.targ_name);
  1301.  
  1302.     /* Target range */
  1303.     r = sqrt (target[t].range2) * KM_TO_UNITS1;
  1304.     sprintf (buf, "%s:%2.0lf", target[t].name, r);
  1305.     Print (GLUT_BITMAP_HELVETICA_10, buf);
  1306.  
  1307.     /* Target shields */
  1308.     TargetShields (t);
  1309.   }
  1310. }
  1311.  
  1312. void WaypointStuff()
  1313. {
  1314.   int w;
  1315.   double r, v[3];
  1316.   char buf[32];
  1317.  
  1318.   if (player.waypoint == (-1)) return;
  1319.  
  1320.   w = player.waypoint;
  1321.   glColor3f (0.8, 0.8, 0.8);
  1322.   glRasterPos2dv (hud.waypoint);
  1323.   Vsub (v, waypoint[w].pos, player.pos);
  1324.   r = Mag (v) * KM_TO_UNITS1;
  1325.   sprintf (buf, "%d:%2.0lf", w+1, r);
  1326.   Print (GLUT_BITMAP_HELVETICA_10, buf);
  1327. }
  1328.  
  1329. void PlayerVel()
  1330. {
  1331.   double r;
  1332.   char buf[64];
  1333.  
  1334.   /* Player velocity */
  1335.   r = Mag (player.vel) * KM_TO_UNITS1;
  1336.  
  1337.   if (r == 0.0)
  1338.   glColor3f (0.0, 0.0, 0.8);
  1339.   else if (Dotp (player.view, player.vel) >= 0.0)
  1340.   glColor3f (0.0, 0.8, 0.0);
  1341.   else
  1342.   glColor3f (0.8, 0.0, 0.0);
  1343.  
  1344.   sprintf (buf, "%2.0lf", r);
  1345.   hud.vel[0] = hud.throt_min[0] - 5 - 
  1346.   glutBitmapLength (GLUT_BITMAP_HELVETICA_10, buf);
  1347.   glRasterPos2dv (hud.vel);
  1348.   Print (GLUT_BITMAP_HELVETICA_10, buf);
  1349. }
  1350.  
  1351. void PlanetStuff()
  1352. {
  1353.   int p;
  1354.   double r;
  1355.   char buf[64];
  1356.  
  1357.   if (-1 == (p = lock.target)) return;
  1358.  
  1359.   if (planet[p].is_moon)
  1360.   glColor3f (0.0, 0.8, 0.8);
  1361.   else
  1362.   glColor3f (0.0, 0.0, 0.8);
  1363.  
  1364.   glRasterPos2dv (hud.targ_name);
  1365.  
  1366.   /* Planet range */
  1367.   r = (sqrt(planet[p].absrange2) - planet[p].radius) * KM_TO_UNITS1;
  1368.   sprintf (buf, "%s:%2.0lf", planet[p].name, r);
  1369.   
  1370.   Print (GLUT_BITMAP_HELVETICA_10, buf);
  1371. }
  1372.  
  1373. void Shields()
  1374. /*
  1375.  *  Draw the shield status
  1376.  */
  1377. {
  1378.   float color[3];
  1379.   double y;
  1380.  
  1381.   glEnable (GL_POLYGON_STIPPLE);
  1382.   glPolygonStipple (throt_stipple);
  1383.  
  1384.   if (player.shields > player.maxshields*0.66)
  1385.   {
  1386.     color[0] = color[2] = 0.0;
  1387.     color[1] = 0.25;
  1388.   }
  1389.   else if (player.shields > player.maxshields*0.33)
  1390.   {
  1391.     color[0] = color[1] = 0.25;
  1392.     color[2] = 0.0;
  1393.   }
  1394.   else
  1395.   {
  1396.     color[0] = 0.25;
  1397.     color[1] = color[2] = 0.0;
  1398.   }
  1399.  
  1400.   y = hud.shields_min[1] +
  1401.   (player.shields / player.maxshields) *
  1402.   (hud.shields_max[1] - hud.shields_min[1]);
  1403.  
  1404.   /* First draw unshaded background */
  1405.   if (player.shields < player.maxshields)
  1406.   {
  1407.     glColor3fv (color);
  1408.     glBegin (GL_QUAD_STRIP);
  1409.     glVertex2d (hud.shields_min[0], y);
  1410.     glVertex2d (hud.shields_max[0], y);
  1411.     glVertex2d (hud.shields_min[0], hud.shields_max[1]);
  1412.     glVertex2d (hud.shields_max[0], hud.shields_max[1]);
  1413.     glEnd();
  1414.   }
  1415.  
  1416.   /* Now show the shields */
  1417.   color[0] *= 3.0;
  1418.   color[1] *= 3.0;
  1419.  
  1420.   glColor3fv (color);
  1421.   glBegin (GL_QUAD_STRIP);
  1422.   glVertex2d (hud.shields_min[0], hud.shields_min[1]);
  1423.   glVertex2d (hud.shields_max[0], hud.shields_min[1]);
  1424.   glVertex2d (hud.shields_min[0], y);
  1425.   glVertex2d (hud.shields_max[0], y);
  1426.   glEnd();
  1427.  
  1428.   glDisable (GL_POLYGON_STIPPLE);
  1429. }
  1430.  
  1431. void ShowWeapon()
  1432. /*
  1433.  *  Show the current weapon
  1434.  */
  1435. {
  1436.   /* Set color depending if it's ready to fire */
  1437.   if (player.msl_idle >= weapon[player.weapon].idle)
  1438.   {
  1439.     glColor3f (0.8, 0.0, 0.8);
  1440.   }
  1441.   else
  1442.   {
  1443.     glColor3f (0.5, 0.5, 0.5);
  1444.   }
  1445.   glRasterPos2dv (hud.weapon);
  1446.   Print (GLUT_BITMAP_HELVETICA_10, weapon[player.weapon].name);
  1447. }
  1448.  
  1449. void TargetShields (int t)
  1450. /*
  1451.  *  Draw the target's shield status
  1452.  */
  1453. {
  1454.   float color[3];
  1455.   double y;
  1456.  
  1457.   glEnable (GL_POLYGON_STIPPLE);
  1458.   glPolygonStipple (throt_stipple);
  1459.  
  1460.   if (target[t].shields > target[t].maxshields*0.66)
  1461.   {
  1462.     color[0] = color[2] = 0.0;
  1463.     color[1] = 0.25;
  1464.   }
  1465.   else if (target[t].shields > target[t].maxshields*0.33)
  1466.   {
  1467.     color[0] = color[1] = 0.25;
  1468.     color[2] = 0.0;
  1469.   }
  1470.   else
  1471.   {
  1472.     color[0] = 0.25;
  1473.     color[1] = color[2] = 0.0;
  1474.   }
  1475.  
  1476.   y = hud.targshields_min[1] +
  1477.   (target[t].shields / target[t].maxshields) *
  1478.   (hud.targshields_max[1] - hud.targshields_min[1]);
  1479.  
  1480.   /* First draw unshaded background */
  1481.   if (target[t].shields < target[t].maxshields)
  1482.   {
  1483.     glColor3fv (color);
  1484.     glBegin (GL_QUAD_STRIP);
  1485.     glVertex2d (hud.targshields_min[0], y);
  1486.     glVertex2d (hud.targshields_max[0], y);
  1487.     glVertex2d (hud.targshields_min[0], hud.targshields_max[1]);
  1488.     glVertex2d (hud.targshields_max[0], hud.targshields_max[1]);
  1489.     glEnd();
  1490.   }
  1491.  
  1492.   /* Now show the shields */
  1493.   color[0] *= 3.0;
  1494.   color[1] *= 3.0;
  1495.  
  1496.   glColor3fv (color);
  1497.   glBegin (GL_QUAD_STRIP);
  1498.   glVertex2d (hud.targshields_min[0], hud.targshields_min[1]);
  1499.   glVertex2d (hud.targshields_max[0], hud.targshields_min[1]);
  1500.   glVertex2d (hud.targshields_min[0], y);
  1501.   glVertex2d (hud.targshields_max[0], y);
  1502.   glEnd();
  1503.  
  1504.   glDisable (GL_POLYGON_STIPPLE);
  1505. }
  1506.